#include "Ball.h"
#include "Geometry.h"

Ball::Ball(float radius)
{
	this->radius = radius;
	DrawSphere(radius, 20, 20, &vbo_high);
	DrawSphere(radius, 10, 10, &vbo_med);
	DrawSphere(radius, 5, 5, &vbo_low);
	detail_level = LOW;
}

void Ball::Draw(void)
{
	glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT);
	glEnable(GL_COLOR_MATERIAL);
	if(ballstate == ENEMY)
	{
		glColor3f(1,0,0);
	}
	else if(ballstate == HEALTH)
	{
		glColor3f(0,1,0);
	}
	else glColor3f(1,1,1);
	switch(detail_level)
	{
	case HIGH: vbo_high.Draw(); break;
	case MEDIUM: vbo_med.Draw(); break;
	case LOW: vbo_low.Draw(); break;
	default: vbo_high.Draw(); break;
	}
	glPopAttrib();
}

void Ball::Update(float delta)
{
	vec3 sMax = wPos + radius, sMin = wPos - radius;

	theRoom->ContainSphere(this);

	if(sMax.x > theRoom->max.x) dir = dir.reflect( vec3(-1,0,0) );
	else if(sMin.x < theRoom->min.x) dir = dir.reflect( vec3(1,0,0) );
	if(sMax.z > theRoom->max.z) dir = dir.reflect( vec3(0,0,-1) );
	else if(sMin.z < theRoom->min.z) dir = dir.reflect( vec3(0,0,1) );

	wPos += dir.normal() * delta * speed;

	if(!bDoCollide && Timer->GetDelay(1000,prevTime)) bDoCollide = true;
}

BallManager::BallManager(Room *room, int Amount, float speed)
: theRoom(room)
{
	for(int i = 0; i < Amount; ++i)
	{
		theBalls.push_back(new Ball( detectzero(RandomNumf(1,8)) ));
		theBalls[i]->ballstate = ENEMY;//(i > 0 + (Amount / 20)) ? ENEMY : HEALTH;
		theBalls[i]->wPos( RandomVec(room->wPos + room->min, room->wPos + room->max) );
		theBalls[i]->dir( RandomVecf( vec3(-1.0f), vec3(1.0f) ).normal() * speed );
		theBalls[i]->wPos.y = 0;
		theBalls[i]->dir.y = 0;
		theBalls[i]->speed = speed;
		theBalls[i]->theRoom = room;
		this->AddChild(theBalls[i]);
	}
}

void BallManager::Update(float delta)
{
	double microTimer;
	Timer->StartCounterPrecise(microTimer);

	Ball *iBall, *jBall;
	// Go through every ball
	for(int i = 0; i < theBalls.size(); ++i)
	{
		iBall = theBalls[i];
		// Go through every other ball
		for(int j = theBalls.size() - 1; j > i; --j)
		{
			jBall = theBalls[j];
			// if they are within the frustum
			// If they are within a certain distance
			// Check for collision
			if( ( iBall->bDraw && jBall->bDraw) &&
				iBall->wPos.distancesquared( jBall->wPos ) < iBall->radius * 2 &&
				iBall->bIntersectsSphere( *jBall ) )
			{
				vec3 temp = iBall->dir;
				iBall->dir = jBall->dir;
				jBall->dir = temp;
				iBall->wPos += iBall->dir * (iBall->radius / 2);
				jBall->wPos += jBall->dir * (jBall->radius / 2);
			}
		}
	}

	BallsCollideTimer = Timer->GetCounterPrecise(microTimer);
}